package cn.iocoder.yudao.module.shop.service.daystatistics;

import cn.hutool.core.date.DateUtil;
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargeDO;
import cn.iocoder.yudao.module.shop.dal.dataobject.item.ShopItemDO;
import cn.iocoder.yudao.module.shop.dal.dataobject.order.ShopOrderDO;
import cn.iocoder.yudao.module.shop.dal.dataobject.order.ShopOrderItemDO;
import cn.iocoder.yudao.module.shop.enums.store.ChargeTypeEnum;
import cn.iocoder.yudao.module.shop.service.item.ShopItemService;
import cn.iocoder.yudao.module.shop.service.order.ShopOrderItemService;
import cn.iocoder.yudao.module.shop.service.order.dto.ShopOrderItemHandleDTO;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.swing.*;

import org.springframework.validation.annotation.Validated;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import cn.iocoder.yudao.module.shop.controller.admin.daystatistics.vo.*;
import cn.iocoder.yudao.module.shop.dal.dataobject.daystatistics.ShopDayStatisticsDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;

import cn.iocoder.yudao.module.shop.convert.daystatistics.ShopDayStatisticsConvert;
import cn.iocoder.yudao.module.shop.dal.mysql.daystatistics.ShopDayStatisticsMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.shop.enums.ErrorCodeConstants.*;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;

/**
 * 每日手工费统计 Service 实现类
 *
 * @author 曹建伟
 */
@Service
@Validated
public class ShopDayStatisticsServiceImpl implements ShopDayStatisticsService {

    @Resource
    private ShopDayStatisticsMapper dayStatisticsMapper;

    @Resource
    private ShopOrderItemService shopOrderItemService;

    @Resource
    private ShopItemService shopItemService;

    @Override
    public Long createDayStatistics(ShopDayStatisticsCreateReqVO createReqVO) {
        // 插入
        ShopDayStatisticsDO dayStatistics = ShopDayStatisticsConvert.INSTANCE.convert(createReqVO);
        dayStatisticsMapper.insert(dayStatistics);
        // 返回
        return dayStatistics.getId();
    }

    @Override
    public void updateDayStatistics(ShopDayStatisticsUpdateReqVO updateReqVO) {
        // 校验存在
        validateDayStatisticsExists(updateReqVO.getId());
        // 更新
        ShopDayStatisticsDO updateObj = ShopDayStatisticsConvert.INSTANCE.convert(updateReqVO);
        dayStatisticsMapper.updateById(updateObj);
    }

    @Override
    public void deleteDayStatistics(Long id) {
        // 校验存在
        validateDayStatisticsExists(id);
        // 删除
        dayStatisticsMapper.deleteById(id);
    }

    private void validateDayStatisticsExists(Long id) {
        if (dayStatisticsMapper.selectById(id) == null) {
            throw exception(DAY_STATISTICS_NOT_EXISTS);
        }
    }

    @Override
    public ShopDayStatisticsDO getDayStatistics(Long id) {
        return dayStatisticsMapper.selectById(id);
    }

    @Override
    public List<ShopDayStatisticsDO> getDayStatisticsList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return ListUtil.empty();
        }
        return dayStatisticsMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<ShopDayStatisticsDO> getDayStatisticsPage(ShopDayStatisticsPageReqVO pageReqVO) {
        return dayStatisticsMapper.selectPage(pageReqVO);
    }

    @Override
    public List<ShopDayStatisticsDO> getDayStatisticsList(ShopDayStatisticsExportReqVO exportReqVO) {
        return dayStatisticsMapper.selectList(exportReqVO);
    }

    private ShopDayStatisticsDO get(String dateId, Long tenantId){
        ShopDayStatisticsDO statisticsDO = dayStatisticsMapper.selectByDateId(dateId, tenantId);

        return statisticsDO;
    }

    private ShopDayStatisticsDO getOrCreate(String dateId, Long tenantId){
        ShopDayStatisticsDO statisticsDO = dayStatisticsMapper.selectByDateId(dateId, tenantId);

        if(statisticsDO == null){
            statisticsDO = new ShopDayStatisticsDO();

            statisticsDO.setTenantId(tenantId);

            statisticsDO.setDateId(dateId); //日期id
            statisticsDO.setTotalCount(0); //总支数
            statisticsDO.setTotalPrice(0); //总流水
            statisticsDO.setWalletPrice(0); //余额流水
            statisticsDO.setCashPrice(0); //现金流水
            statisticsDO.setTimesCharge(0); //次数支付

            statisticsDO.setTotalMemberTimes(0); //总人次
            statisticsDO.setVipTimes(0); //会员人次
            statisticsDO.setNovipTimes(0); //非会员人次
            statisticsDO.setNewMemberCount(0); //新人进店人次


            statisticsDO.setChargeTotalCount(0); //充值人数
            statisticsDO.setChargeTotalPrice(0); //充值总金额
            statisticsDO.setChargeContinueCount(0); //续充人数
            statisticsDO.setChargeNoContinueCount(0); //未续充人次
            statisticsDO.setChargeFirstCount(0); //首充人次
            statisticsDO.setChargeAfterTimesCount(0); //大于1次之后充值人次

            LocalDateTime now = LocalDateTime.now();
            statisticsDO.setCreateTime(now);
            statisticsDO.setUpdateTime(now);

            dayStatisticsMapper.insert(statisticsDO);

            statisticsDO = dayStatisticsMapper.selectByDateId(dateId, tenantId);

            return  statisticsDO;
        }

        return statisticsDO;
    }

    @Override
    public Boolean recordOrder(ShopOrderDO order, Boolean isNewMember, Long rechargeOrderCount){
        String dateId = order.getStartTime().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        ShopDayStatisticsDO statisticsDO = getOrCreate(dateId, order.getTenantId());

        if(statisticsDO == null){
            throw exception(DAY_STATISTICS_CREATE_ERROR);
        }

        statisticsDO.setCreateTime(order.getStartTime());
        statisticsDO.setUpdateTime(order.getStartTime());

        ShopOrderItemHandleDTO handleDTO = shopOrderItemService.getHandleByOrderId(order.getId());

        statisticsDO.setTotalCount(statisticsDO.getTotalCount() + handleDTO.getHandleCount());

        statisticsDO.setTotalPrice(statisticsDO.getTotalPrice() + order.getPayPrice());
        if(order.getWalletCharge()){
            statisticsDO.setWalletPrice(statisticsDO.getWalletPrice() + order.getPayPrice());
        }else if(order.getTimesCharge()){
            statisticsDO.setTimesCharge(statisticsDO.getTimesCharge() + 1);
        }else {
            statisticsDO.setCashPrice(statisticsDO.getCashPrice() + order.getPayPrice());
            if(rechargeOrderCount > 0){
                statisticsDO.setChargeNoContinueCount(statisticsDO.getChargeNoContinueCount() + 1);
            }
        }

        statisticsDO.setTotalMemberTimes(statisticsDO.getTotalMemberTimes() + 1);
        if(order.getWalletCharge()){
            statisticsDO.setVipTimes(statisticsDO.getVipTimes() + 1);
        }else{
            statisticsDO.setNovipTimes(statisticsDO.getNovipTimes() + 1);
        }

        if(isNewMember){
            statisticsDO.setNewMemberCount(statisticsDO.getNewMemberCount() + 1);
        }

        dayStatisticsMapper.updateById(statisticsDO);

        return true;
    }

    @Override
    public Boolean rollbackOrder(ShopOrderDO order){
        String dateId = order.getStartTime().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        ShopDayStatisticsDO statisticsDO = get(dateId, order.getTenantId());

        if(statisticsDO == null){
            return true;
        }

        ShopOrderItemHandleDTO handleDTO = shopOrderItemService.getHandleByOrderId(order.getId());

        statisticsDO.setTotalCount(statisticsDO.getTotalCount() - handleDTO.getHandleCount());

        statisticsDO.setTotalPrice(statisticsDO.getTotalPrice() - order.getPayPrice());
        if(order.getWalletCharge()){
            statisticsDO.setWalletPrice(statisticsDO.getWalletPrice() - order.getPayPrice());
        }else if(order.getTimesCharge()){
            statisticsDO.setTimesCharge(statisticsDO.getTimesCharge() - 1);
        }else {
            statisticsDO.setCashPrice(statisticsDO.getCashPrice() - order.getPayPrice());
        }

        statisticsDO.setTotalMemberTimes(statisticsDO.getTotalMemberTimes() - 1);
        if(order.getWalletCharge()){
            statisticsDO.setVipTimes(statisticsDO.getVipTimes() - 1);
        }else{
            statisticsDO.setNovipTimes(statisticsDO.getNovipTimes() - 1);
        }

        dayStatisticsMapper.updateById(statisticsDO);

        return true;
    }

    @Override
    public Boolean recordPayOrder(PayWalletRechargeDO payOrder, Long masterId, ChargeTypeEnum chargeType){
        String dateId = payOrder.getCreateTime().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        ShopDayStatisticsDO statisticsDO = getOrCreate(dateId, payOrder.getTenantId());

        statisticsDO.setChargeTotalCount(statisticsDO.getChargeTotalCount() + 1);
        statisticsDO.setChargeTotalPrice(statisticsDO.getChargeTotalPrice() + payOrder.getPayPrice());

        if(chargeType.getType().equals(ChargeTypeEnum.FIRST.getType())){
            statisticsDO.setChargeFirstCount(statisticsDO.getChargeFirstCount() + 1);
        }else if(chargeType.getType().equals(ChargeTypeEnum.CONTINUE.getType())){
            statisticsDO.setChargeContinueCount(statisticsDO.getChargeContinueCount() + 1);
        }else if(chargeType.getType().equals(ChargeTypeEnum.CONVERT.getType())){
            statisticsDO.setChargeAfterTimesCount(statisticsDO.getChargeAfterTimesCount() + 1);
        }

        dayStatisticsMapper.updateById(statisticsDO);

        return true;
    }

    public Boolean recordTimesChargePay(Integer payPrice, Long memberId, Long masterId, ChargeTypeEnum chargeType, Long tenantId){
        String dateId = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        ShopDayStatisticsDO statisticsDO = getOrCreate(dateId, tenantId);

        statisticsDO.setChargeTotalCount(statisticsDO.getChargeTotalCount() + 1);
        statisticsDO.setChargeTotalPrice(statisticsDO.getChargeTotalPrice() + payPrice);

        if(chargeType.getType().equals(ChargeTypeEnum.FIRST.getType())){
            statisticsDO.setChargeFirstCount(statisticsDO.getChargeFirstCount() + 1);
        }else if(chargeType.getType().equals(ChargeTypeEnum.CONTINUE.getType())){
            statisticsDO.setChargeContinueCount(statisticsDO.getChargeContinueCount() + 1);
        }else if(chargeType.getType().equals(ChargeTypeEnum.CONVERT.getType())){
            statisticsDO.setChargeAfterTimesCount(statisticsDO.getChargeAfterTimesCount() + 1);
        }

        dayStatisticsMapper.updateById(statisticsDO);

        return true;
    }

    @Override
    public List<ShopDayStatisticsDO> getDayStatisticsListByTime(LocalDateTime startTime, LocalDateTime endTime, Long tenantId){
        return dayStatisticsMapper.selectList(startTime, endTime, tenantId);
    }

    @Override
    public ShopDayStatisticsDO getDayStatisticsByDateId(String dateId, Long tenantId){
        return dayStatisticsMapper.selectByDateId(dateId, tenantId);
    }

    @Override
    public void dayJob(List<Long> tenantIds){
        if(tenantIds.isEmpty()){
            return;
        }

        String dateId = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));

        for(int i = 0; i<tenantIds.size(); i++){
            Long tenantId = tenantIds.get(i);
            getOrCreate(dateId, tenantId);
        }
    }

}
